﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Microsoft.SqlServer.Management.Smo;
using Microsoft.SqlServer.Management.UI.VSIntegration;
using Microsoft.SqlServer.Management.UI.VSIntegration.ObjectExplorer;

namespace SsmsAddin
{
    public partial class UcExtendProperties : UserControl
    {
        private static string _databasename;
        protected internal static bool Initializing = true;
        private static Database _mydb;
        private static string _serverConnection;
        private static string _spName;
        private static Server _theServer;
        private BindingSource _dataSource;
        private BindingList<MyExtendProperty> _extendProperties;

        public UcExtendProperties()
        {
            InitializeComponent();
        }

        private void BindFieldGrid()
        {
            DGV_Field.AutoGenerateColumns = false;
            var column3 = new DataGridViewTextBoxColumn
                          {
                              DataPropertyName = "ObjectName",
                              HeaderText = "Field Name",
                              ReadOnly = true,
                              AutoSizeMode = DataGridViewAutoSizeColumnMode.DisplayedCellsExceptHeader
                          };
            DataGridViewTextBoxColumn dataGridViewColumn = column3;
            var column4 = new DataGridViewTextBoxColumn
                          {
                              DataPropertyName = "Value",
                              HeaderText = "Description",
                              AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill
                          };
            DataGridViewTextBoxColumn column2 = column4;
            DGV_Field.Columns.Clear();
            DGV_Field.Columns.Add(dataGridViewColumn);
            DGV_Field.Columns.Add(column2);
            DGV_Field.DataSource = GetListField();
        }

        private void BindTableGrid()
        {
            DGV_table.AutoGenerateColumns = false;
            var column3 = new DataGridViewTextBoxColumn
                          {
                              DataPropertyName = "Name",
                              HeaderText = "Property",
                              ReadOnly = false,
                              AutoSizeMode = DataGridViewAutoSizeColumnMode.DisplayedCellsExceptHeader
                          };
            DataGridViewTextBoxColumn dataGridViewColumn = column3;
            var column4 = new DataGridViewTextBoxColumn
                          {
                              DataPropertyName = "Value",
                              HeaderText = "Value",
                              AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill
                          };
            DataGridViewTextBoxColumn column2 = column4;

            DGV_table.Columns.Clear();
            DGV_table.Columns.Add(dataGridViewColumn);
            DGV_table.Columns.Add(column2);

            var lstTableProperties = (List<MyExtendProperty>) GetTableExtendProperties();
            _extendProperties = new BindingList<MyExtendProperty>(lstTableProperties);
            DGV_table.DataSource = _extendProperties;

            _dataSource = new BindingSource {DataSource = lstTableProperties};
            _dataSource.AddingNew += delegate(object sender, AddingNewEventArgs e)
                                         {
                                             e.NewObject = new MyExtendProperty(_mydb.Tables[_spName], "New Property", _spName, "New Property");
                                         };

            DGV_table.DataSource = _dataSource;
            DGV_table.AllowUserToAddRows = true;
            DGV_table.AllowUserToDeleteRows = true;
        }

        private void btnSave_Click(object sender, EventArgs e)
        {
            fnScript(_mydb.Tables[_spName], true);
        }

        private void fnScript(IScriptable thing, bool scriptDrop)
        {
            string str = getFileName();
            if (string.IsNullOrEmpty(str)) return;
            var options3 = new ScriptingOptions
                           {
                               AppendToFile = true,
                               FileName = str,
                               Encoding = Encoding.Default,
                               ScriptDrops = true,
                               IncludeDatabaseContext = false,
                               IncludeIfNotExists = true,
                               ClusteredIndexes = true,
                               DriAll = true,
                               ExtendedProperties = true,
                               Indexes = true,
                               NonClusteredIndexes = true,
                               Permissions = true,
                               Triggers = true
                           };
            ScriptingOptions scriptingOptions = options3;
            scriptingOptions.Permissions = true;
            var options4 = new ScriptingOptions
                           {
                               AppendToFile = true,
                               FileName = str,
                               Encoding = Encoding.Default,
                               ScriptDrops = false,
                               IncludeDatabaseContext = false,
                               IncludeIfNotExists = false,
                               ClusteredIndexes = true,
                               DriAll = true,
                               ExtendedProperties = true,
                               Indexes = true,
                               NonClusteredIndexes = true,
                               Permissions = true,
                               Triggers = true
                           };
            ScriptingOptions options2 = options4;
            options2.Permissions = true;
            if (!(thing is Table)) return;
            foreach (ExtendedProperty property in ((Table) thing).ExtendedProperties)
            {
                property.Script(scriptingOptions);
                property.Script(options2);
            }
            foreach (ExtendedProperty property2 in ((Table) thing).Columns.Cast<Column>().SelectMany(column => column.ExtendedProperties.Cast<ExtendedProperty>()))
            {
                property2.Script(scriptingOptions);
                property2.Script(options2);
            }
        }

        private static string getFileName()
        {
            var dialog = new SaveFileDialog
                         {
                             FileName = _spName + ".SQL",
                             Filter = "Fichier SQL|*.SQL",
                             Title = "Save extended properties"
                         };
            dialog.ShowDialog();
            return dialog.FileName;
        }

        private static ICollection<MyExtendProperty> GetListField()
        {
            return Utils._DBNode.objectType != MenuItem.ObjectType.Table.ToString() ? null : (from c in _mydb.Tables[_spName].Columns.Cast<Column>() select new MyExtendProperty {SmoObject = c, ObjectName = c.Name, Name = "MS_Description", Value = (c.ExtendedProperties["MS_Description"] != null) ? c.ExtendedProperties["MS_Description"].Value.ToString() : ""}).ToList();
        }

        private static void GetSMOInformations()
        {
            _serverConnection = Utils._DBNode.serverName;
            _spName = Utils._DBNode.objectName;
            _databasename = Utils._DBNode.dbName;
            if (_serverConnection != null)
            {
                _theServer = new Server(_serverConnection);
            }
            if (_databasename != null)
            {
                _mydb = _theServer.Databases[_databasename];
            }
        }

        private static ICollection<MyExtendProperty> GetTableExtendProperties()
        {
            return
                (from ExtendedProperty property in _mydb.Tables[_spName].ExtendedProperties
                 select new MyExtendProperty
                        {
                            SmoObject = _mydb.Tables[_spName], Name = property.Name, Value = property.Value.ToString()
                        }).ToList();
        }


        protected override void OnLoad(EventArgs e)
        {
            UpdateObjectExplorerInfo();
            var service = (IObjectExplorerEventProvider) ServiceCache.GetObjectExplorer().GetService(typeof (IObjectExplorerEventProvider));
            service.SelectionChanged += ProviderSelectionChanged;
        }

        private void ProviderSelectionChanged(object sender, NodesChangedEventArgs args)
        {
            UpdateObjectExplorerInfo();
            if (string.IsNullOrEmpty(_spName) || (Utils._DBNode.objectType != MenuItem.ObjectType.Table.ToString()))
            {
                DGV_table.DataSource = null;
                DGV_Field.DataSource = null;
                return;
            }
            Initializing = true;
            BindTableGrid();
            BindFieldGrid();
            Initializing = false;
        }

        private static void UpdateObjectExplorerInfo()
        {
            Utils.UpdateObjectExplorerInfo();
            GetSMOInformations();
        }

        private void toolStripButton3_Click(object sender, EventArgs e)
        {
            if (DGV_table.CurrentRow == null)
            {
                MessageBox.Show("Selectionnez une ligne à supprimer", "Attention !", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                return;
            }
            if (MessageBox.Show("Voulez-vous supprimer cette propriété étendue ?", "Question", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.No)
                return;

            var currentExtendProperty = (MyExtendProperty)_dataSource.Current;
            currentExtendProperty.RemoveMe();
            DGV_table.Rows.Remove(DGV_table.CurrentRow);
        }

        private void DGV_table_SelectionChanged(object sender, EventArgs e)
        {
        }
    }
}